home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Programmer Disk
/
The Programmer Disk (Microforum).iso
/
xpro
/
c4
/
pro17
/
no.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-04
|
6KB
|
235 lines
/*
Program title: no.c
Purpose: Rewrite of a classic utility for those who still
use the DOS command-line interface ...
Excludes filespec from a command-line operation.
e.g. NO *.BAT ERASE *.* would delete everything
EXCEPT batch files in current directory.
Author: Michael Salera (idea by Charles Petzold)
Release: P.D. / shareware (see no.doc)
*/
#include <stdlib.h>
#include <stdio.h>
#include <dir.h> /* non-standard headers */
#include <dos.h> /* os2.h ?? */
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <process.h>
#include "lists.h" /* linked-list data structures */
#define FNAME_STR 13 /* 13-byte string for filename */
#define NDEBUG
/*
#define NDEBUG for "no debugging" if this were to become
a finished product. Squelches all assert(expression) macros.
Compiler details - this was compiled & linked using Borland's
Turbo C++ 1.0 with absolutely no C++ extensions, so that MSC 5.1+
should also compile this with few problems.
The whole reason I bothered to write this utility was to try to port
it to OS/2 1.3, which I now work with. However, since I have little
documentation on the IBM C/2 compiler, this program still needs to
replace DOS-specific code with OS/2 functions.
*/
/*
The command line args are everything to this program:
argv[1] argv[2] argv[3]
*.CMD DEL *.*
what to exclude
actual command
command parms.
1. Basically argv[1] must be expanded from its wildcard state
(*.CMD) into a linked list of actual filespecs to be hidden.
findfirst() / DosFindFirst() takes care of this.
2. Function hide_diskfile(const char* path) will successively
hide each file.
3. Once the hidden attribute is set, then the next step is to
spawnl( P_WAIT mode!... ) the command and make sure it
gets its parameters.
4. Function un_hide_diskfile(const char* path) takes the old list
and, as one might guess, resets the archive attribute.
5. Free the space allocated for the list and exit.
*/
/* P R O T O T Y P E S */
LINK expand_wc(const char *wildcard); /* returns pointer to newly created list */
void hide_diskfile(const char *path);
void un_hide_diskfile(const char *path);
/* returns how many were in list for diagnostic or statistical purposes,
"NO excluded 5 files" ... */
int cleanup(LINK head);
/* D E F I N I T I O N S */
/* returns pointer to newly created list - or NULL if no file matches
the wildcard spec. given */
LINK expand_wc(const char *wildcard)
{
LINK head, tail;
struct ffblk dirinfo;
int done;
/* findfirst() is a DOS-SPECIFIC function */
if (done = findfirst(wildcard, &dirinfo, FA_ARCH))
return (NULL); /* not even one match ! */
/* list is empty - initialize pointers to new node */
head = tail = (LINK) malloc(sizeof(ELEMENT));
while (!done) {
/* copy filename to info field */
tail -> info = (DATA) malloc(FNAME_STR);
strcpy(tail -> info, dirinfo.ff_name);
/* findnext() is a DOS-SPECIFIC function */
if (done = findnext(&dirinfo)) { /* no more matches - end list */
tail -> next = NULL;
}
/* if more filenames then create link - done == 0 on success */
else {
tail -> next = (LINK) malloc(sizeof(ELEMENT));
tail = tail -> next;
}
}
assert(done); assert(head != NULL);
return (head);
}
/* _chmod() is a DOS-SPECIFIC function */
void hide_diskfile(const char *path)
{
int errcode;
errcode = _chmod(path, 1, FA_HIDDEN);
assert(errcode == FA_HIDDEN);
}
/* _chmod() is a DOS-SPECIFIC function */
void un_hide_diskfile(const char *path)
{
int errcode;
errcode = _chmod(path, 1, FA_ARCH);
assert(errcode == FA_ARCH);
}
/* returns how many were in list for diagnostic or statistical purposes,
"NO excluded 5 files ..." */
int cleanup(LINK head)
{
LINK temp_ptr;
int num_in_list = 0;
while (head) {
++num_in_list;
/* unlink first node from the list */
temp_ptr = head;
head = head -> next;
/* start freeing nodes */
free(temp_ptr);
}
return (num_in_list);
}
/* P R O G R A M B E G I N S */
int main(int argc, char *argv[])
{
LINK head, trail_ptr;
const char *cmd_line_typo = "NO: usage is NO <filespec> <cmd> [<parms>]";
const char *file_typo = "NO: error in filespec - file(s) non existent";
char *path = "COMMAND.COM";
char *cmd_parms = "/c "; /* would be "cmd /c" under OS/2 */
int num_hid;
if ((argc < 3) || (argc > 4)) { /* cmd.-line checkup */
fprintf(stderr, "%s\n\n", cmd_line_typo);
return (1);
}
if ((head = expand_wc(argv[1])) == NULL) {
fprintf(stderr, "%s\n\n", file_typo);
return (1);
}
/* Command-line args are OK, head now points to a list of files
to be hidden. Now traverse list and hide each */
trail_ptr = head;
while (trail_ptr) {
hide_diskfile(trail_ptr -> info);
trail_ptr = trail_ptr -> next;
}
/* Building the actual command line & exec child process.
all are preceded by "command /c" in case of internal "dir,"
"del," "type," etc. */
strcat(cmd_parms, argv[2]); /* required */
if (argv[3] != NULL) {
strcat(cmd_parms, " "); /* add third parameter to spawn */
strcat(cmd_parms, argv[3]);
}
if (spawnlp(P_WAIT, path, argv[0], cmd_parms, NULL) == -1)
switch (errno) {
case EINVAL: fprintf(stderr, "Invalid argument.");
break;
case ENOENT: fprintf(stderr, "Path or file name not found.");
break;
case ENOEXEC: fprintf(stderr, "Exec format error.");
break;
case ENOMEM: fprintf(stderr, "Not enough core memory.");
break;
default: fprintf(stderr, "Error number: %d", errno);
}
/* Now traverse & un-hide */
trail_ptr = head;
while (trail_ptr) {
un_hide_diskfile(trail_ptr -> info);
trail_ptr = trail_ptr -> next;
}
num_hid = cleanup(head); /* let's be neat! */
fprintf(stdout, "\nNO excluded %d files from command.\n", num_hid);
return (0);
}